package com.xiaoma.verbal.component;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import net.sf.json.JSONObject;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.protocol.HTTP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.xiaoma.verbal.dao.PrctPracticeAudioDao;

@Component
public class AsynPushClient {
	/**
	 * @param args
	 * @throws IOReactorException
	 * @throws InterruptedException
	 */
	private List<Object[]> objs;
	@Autowired
	private HandlerFailThread failHandler;
	@Autowired
	private HandlerSucThread sucHandler;
	private static final String APPLICATION_JSON = "application/json";

	private static final String CONTENT_TYPE_TEXT_JSON = "text/json";
	private static final Logger LOG = LoggerFactory.getLogger(AsynPushClient.class);

	public void init(List<Object[]> objs) {
		this.objs = objs;
	}

	public Map<String, String> asynPost() throws IOReactorException, InterruptedException {
		final CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault();
		httpclient.start();
		int objLength = objs.size();
		HttpPost[] posts = new HttpPost[objLength];
		int i = 0;
		for (Object[] obj : objs) {
			String url = obj[0].toString();
			String json = obj[1].toString();
			try {
				String newstring = new String(json.toString().getBytes("UTF-8"), "iso-8859-1");
				LOG.info(newstring);
				StringEntity se = new StringEntity(newstring);
				posts[i] = new HttpPost(url);
				posts[i].addHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);

				se.setContentType(CONTENT_TYPE_TEXT_JSON);
				se.setContentEncoding(HTTP.UTF_8);
				posts[i].setEntity(se);
				i++;
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		final CountDownLatch latch = new CountDownLatch(posts.length);
		final Map<String, String> postMap = new HashMap<String, String>();
		try {
			for (int j = 0; j < posts.length; j++) {
				final HttpPost post = posts[j];
				final Object audioId = objs.get(j)[2];
				httpclient.execute(post, new FutureCallback<HttpResponse>() {
					public void completed(final HttpResponse response) {
						latch.countDown();
						postMap.put(post.getURI().toString(), response.getStatusLine().toString());
						try {
							int status = response.getStatusLine().getStatusCode();
							String result = "";
							if (status == 200 && (result = readInputStream(response.getEntity().getContent())) != null && !"".equals(result)
									&& JSONObject.fromObject(result).getInt("status") == 1) {
								sucHandler.putSuc(audioId);
							} else {
								JSONObject json = JSONObject.fromObject(result);
								String msg = json.getString("message");
								if(msg.equals("answer_id is already exists")){
									sucHandler.putSuc(audioId);
								}else{
									LOG.debug("FAIL:{}",readInputStream(post.getEntity().getContent()));
									failHandler.putFail(post.getURI().toString(), response.getStatusLine().toString()+result);
								}
								
							}
						} catch (IllegalStateException e) {
							failHandler.putFail(post.getURI().toString(), response.getStatusLine().toString());
							e.printStackTrace();
						} catch (Exception e) {
							failHandler.putFail(post.getURI().toString(), response.getStatusLine().toString());
							e.printStackTrace();
						}
					}

					public void failed(final Exception ex) {
						latch.countDown();
						ex.printStackTrace();
						failHandler.putFail(post.getURI().toString(), ex.getMessage());
					}

					public void cancelled() {
						latch.countDown();
					}

				});
			}
		} finally {
			latch.await();
			try {
				httpclient.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		failHandler.printFailUrl();
		try {
			System.out.println(sucHandler.hashCode());
			sucHandler.complete();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		
		return postMap;
	}

	private String readInputStream(InputStream input) throws IOException {
		byte[] buffer = new byte[128];
		int len = 0;
		ByteArrayOutputStream bytes = new ByteArrayOutputStream();
		while ((len = input.read(buffer)) >= 0) {
			bytes.write(buffer, 0, len);
		}
		return bytes.toString();
	}

	/**
	 * Test
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		List<String[]> urls = new ArrayList<String[]>();
		String[] parms = new String[3];
		// parms[0] =
		// "http://192.168.1.225:8080/xmpg/xbpg/service/submitToeflPractice";
		parms[0] = "http://192.168.1.162:8080/xmpg/xbpg/service/submitToeflPractice";
		// parms[0]="http://192.168.1.33/service/auditor/test";
		parms[1] = "{}";
		parms[2] = "http://192.168.1.33/service/auditor/updateTrainingStatus";
		urls.add(parms);
		for (int i = 0; i < 1; i++) {
			urls.addAll(urls);
		}
		System.out.println(urls.size());
		AsynPushClient client = new AsynPushClient();
		try {
			client.asynPost();
		} catch (IOReactorException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("done");
	}
}
